Multi-threaded I/O operations হল এমন একটি পদ্ধতি যেখানে একাধিক থ্রেড I/O (Input/Output) অপারেশন একসাথে, অথবা বিভিন্ন সময়ে পরিচালনা করে। এটি পারফরম্যান্স উন্নত করতে ব্যবহৃত হয়, বিশেষ করে যখন একাধিক I/O অপারেশন (যেমন ফাইল পড়া/লেখা, নেটওয়ার্ক কল) একই সময়ে একাধিক থ্রেডের মাধ্যমে সম্পাদন করতে হয়।
Java-তে multi-threaded I/O operations সাধারণত Threading, ExecutorService, এবং Synchronous/Asynchronous I/O এর মাধ্যমে পরিচালিত হয়।
এই উদাহরণে দুটি থ্রেড তৈরি করা হয়েছে, একটি ফাইল পড়বে এবং অন্যটি ফাইলে লিখবে।
import java.io.*;
import java.util.concurrent.*;
public class MultiThreadedIOExample {
public static void main(String[] args) throws InterruptedException, ExecutionException {
// ExecutorService তৈরি
ExecutorService executorService = Executors.newFixedThreadPool(2);
// ফাইল লেখার জন্য থ্রেড
Future<Void> writeTask = executorService.submit(new FileWriterTask());
// ফাইল পড়ার জন্য থ্রেড
Future<Void> readTask = executorService.submit(new FileReaderTask());
// থ্রেডের কাজ শেষ হওয়া পর্যন্ত অপেক্ষা করুন
writeTask.get();
readTask.get();
// ExecutorService বন্ধ করা
executorService.shutdown();
}
static class FileWriterTask implements Callable<Void> {
@Override
public Void call() throws IOException {
try (BufferedWriter writer = new BufferedWriter(new FileWriter("file.txt"))) {
writer.write("Hello from the Writer Thread!\n");
System.out.println("Data written to file.");
}
return null;
}
}
static class FileReaderTask implements Callable<Void> {
@Override
public Void call() throws IOException {
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println("Reading: " + line);
}
}
return null;
}
}
}
ব্যাখ্যা:
ExecutorService
ব্যবহার করা হয়েছে যা থ্রেড ব্যবস্থাপনা সহজ করে তোলে।আউটপুট:
Data written to file.
Reading: Hello from the Writer Thread!
এই উদাহরণে একটি ফাইলকে অনেকগুলি অংশে বিভক্ত করা হয়েছে এবং প্রতিটি অংশ আলাদা থ্রেড দ্বারা কপি করা হয়েছে।
import java.io.*;
import java.util.concurrent.*;
public class MultiThreadedFileCopy {
public static void main(String[] args) throws InterruptedException, ExecutionException {
File sourceFile = new File("source.txt");
File destinationFile = new File("destination.txt");
// ExecutorService তৈরি
ExecutorService executor = Executors.newFixedThreadPool(4);
// ফাইলের আকার
long fileSize = sourceFile.length();
long partSize = fileSize / 4;
// থ্রেড গুলি পাঠানো হবে
Future<Void> task1 = executor.submit(new FileCopyTask(sourceFile, destinationFile, 0, partSize));
Future<Void> task2 = executor.submit(new FileCopyTask(sourceFile, destinationFile, partSize, partSize * 2));
Future<Void> task3 = executor.submit(new FileCopyTask(sourceFile, destinationFile, partSize * 2, partSize * 3));
Future<Void> task4 = executor.submit(new FileCopyTask(sourceFile, destinationFile, partSize * 3, fileSize));
// কাজ শেষ হওয়া পর্যন্ত অপেক্ষা করুন
task1.get();
task2.get();
task3.get();
task4.get();
// ExecutorService বন্ধ করা
executor.shutdown();
System.out.println("File copied successfully using multiple threads.");
}
static class FileCopyTask implements Callable<Void> {
private final File source;
private final File destination;
private final long start;
private final long end;
public FileCopyTask(File source, File destination, long start, long end) {
this.source = source;
this.destination = destination;
this.start = start;
this.end = end;
}
@Override
public Void call() throws IOException {
try (RandomAccessFile sourceFile = new RandomAccessFile(source, "r");
RandomAccessFile destFile = new RandomAccessFile(destination, "rw")) {
sourceFile.seek(start);
destFile.seek(start);
byte[] buffer = new byte[1024];
long bytesRead = start;
while (bytesRead < end) {
int read = sourceFile.read(buffer);
if (read == -1) break;
destFile.write(buffer, 0, read);
bytesRead += read;
}
}
return null;
}
}
}
ব্যাখ্যা:
FileCopyTask
ক্লাসে একটি নির্দিষ্ট অংশ থেকে ফাইল কপি করার জন্য থ্রেড তৈরি করা হয়েছে।ExecutorService
ব্যবহার করে 4টি থ্রেড তৈরি করা হয়েছে, প্রতিটি থ্রেড একটি নির্দিষ্ট ফাইল অংশ কপি করবে।RandomAccessFile
ব্যবহার করে নির্দিষ্ট অংশ থেকে ফাইল পড়া এবং লেখা হচ্ছে।আউটপুট:
File copied successfully using multiple threads.
Multi-threaded I/O operations Java-তে থ্রেড এবং ExecutorService ব্যবহার করে একাধিক I/O অপারেশন কার্যকরীভাবে সম্পন্ন করার একটি কৌশল। এটি কেবলমাত্র থ্রেড সিঙ্ক্রোনাইজেশন এবং রিসোর্স ব্যবস্থাপনা উন্নত করে না, বরং performance এবং scalability বৃদ্ধিতেও সাহায্য করে।
Java Tuples ব্যবহার করে আপনি একাধিক I/O অপারেশন থেকে প্রাপ্ত ডেটা সংরক্ষণ এবং প্রসেস করতে পারেন, যা ডেটার আরও ভালো পরিচালনা নিশ্চিত করে।
Multi-threading হল একধরনের প্রোগ্রামিং পদ্ধতি, যেখানে একাধিক থ্রেড (threads) একসাথে কাজ করে, যা একটি প্রোগ্রামের কার্যকারিতা উন্নত করতে সাহায্য করে। Java-তে multi-threading এর মাধ্যমে একাধিক কার্যক্রম (tasks) একসাথে (concurrently) সম্পন্ন করা যায়, যা পারফরম্যান্স এবং প্রতিক্রিয়া সময় (response time) অনেক উন্নত করতে পারে।
Multi-threading প্রোগ্রামিং ভাষায় বিভিন্ন কার্যক্রম বা কাজ একসাথে চালানোর পদ্ধতি, যা প্রসেসরের ব্যবহারকে আরও দক্ষ এবং প্রতিযোগিতামূলক করে তোলে।
Java-তে multi-threading ব্যবহার করার জন্য Thread
ক্লাস বা Runnable
ইন্টারফেস ব্যবহার করা হয়। নিচে একটি উদাহরণ দেওয়া হয়েছে, যেখানে দুটি থ্রেড একসাথে কাজ করছে।
class MyThread extends Thread {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getId() + " Value: " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class MultiThreadExample {
public static void main(String[] args) {
MyThread t1 = new MyThread(); // Create thread 1
MyThread t2 = new MyThread(); // Create thread 2
t1.start(); // Start thread 1
t2.start(); // Start thread 2
}
}
ব্যাখ্যা:
run()
মেথডের মাধ্যমে থ্রেডের কার্যকলাপ সংজ্ঞায়িত করা হয়েছে।start()
মেথড ব্যবহার করে থ্রেড চালু করা হয়।sleep()
মেথড ব্যবহার করা হয়েছে থ্রেডের কার্যক্রমকে বিরতি দেওয়ার জন্য।আউটপুট:
1 Value: 0
1 Value: 1
2 Value: 0
1 Value: 2
2 Value: 1
1 Value: 3
2 Value: 2
1 Value: 4
2 Value: 3
Thread
ক্লাস ব্যবহার করে Java তে একটি নতুন থ্রেড তৈরি করা হয়। run()
মেথড থ্রেডটি যা কাজ করবে তা নির্ধারণ করে।run()
মেথডে থ্রেডের কার্যকলাপ নির্ধারণ করা হয়।ExecutorService
ক্লাস Java 5 এ যোগ করা হয়েছিল এবং এটি থ্রেড পুল ব্যবস্থাপনা ও থ্রেড অ্যাসাইনমেন্টের কাজ সহজ করে তোলে।java.util.concurrent
প্যাকেজে বিভিন্ন কনকারেন্সি ইউটিলিটি রয়েছে, যেমন CountDownLatch, Semaphore, Executor ইত্যাদি, যা একাধিক থ্রেড পরিচালনার জন্য ব্যবহৃত হয়।I/O Synchronization হল একটি গুরুত্বপূর্ণ কৌশল যখন একাধিক থ্রেড একযোগে I/O অপারেশন পরিচালনা করে। যখন একাধিক থ্রেড একে অপরের সাথে একই রিসোর্স (যেমন একটি ফাইল বা ডাটাবেস) অ্যাক্সেস করে, তখন Thread Safety নিশ্চিত করতে I/O অপারেশনগুলোকে synchronized করা প্রয়োজন।
Java তে I/O Synchronization এর জন্য synchronized blocks বা locks ব্যবহৃত হয়, যাতে এক থ্রেড যখন I/O অপারেশন করছে, তখন অন্য কোন থ্রেড একই রিসোর্স অ্যাক্সেস করতে না পারে এবং data consistency বজায় থাকে।
I/O Synchronization করার জন্য কয়েকটি কৌশল ব্যবহার করা যায়:
import java.io.*;
import java.util.concurrent.*;
public class SynchronizedMethodExample {
private static final Object lock = new Object(); // Lock object
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(2); // Two threads
// Thread 1: Writes to file
executor.submit(() -> {
synchronized (lock) {
writeToFile("file1.txt", "Thread 1: Writing to file.");
}
});
// Thread 2: Writes to file
executor.submit(() -> {
synchronized (lock) {
writeToFile("file2.txt", "Thread 2: Writing to file.");
}
});
executor.shutdown(); // Shut down the executor
}
// Synchronized I/O method
public static void writeToFile(String fileName, String data) {
try (FileWriter writer = new FileWriter(fileName)) {
writer.write(data);
System.out.println(data + " (Written to " + fileName + ")");
} catch (IOException e) {
e.printStackTrace();
}
}
}
ব্যাখ্যা:
writeToFile
মেথডটি synchronized করা হয়েছে, যার মানে এক সময়ে এক থ্রেডই এই মেথডটি অ্যাক্সেস করতে পারবে।ExecutorService
ব্যবহার করা হয়েছে দুটি থ্রেড চালানোর জন্য।import java.io.*;
import java.util.concurrent.*;
public class SynchronizedBlockExample {
private static final Object lock = new Object(); // Lock object
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(2); // Two threads
// Thread 1: Writes to file
executor.submit(() -> {
writeToFile("file1.txt", "Thread 1: Writing to file.");
});
// Thread 2: Writes to file
executor.submit(() -> {
writeToFile("file2.txt", "Thread 2: Writing to file.");
});
executor.shutdown(); // Shut down the executor
}
// Synchronized I/O method
public static void writeToFile(String fileName, String data) {
synchronized (lock) {
try (FileWriter writer = new FileWriter(fileName)) {
writer.write(data);
System.out.println(data + " (Written to " + fileName + ")");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
ব্যাখ্যা:
writeToFile
মেথডের মধ্যে synchronized block ব্যবহার করা হয়েছে, যাতে একে একে ফাইল লেখার অপারেশন সম্পন্ন হয়।import java.io.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockExample {
private static final Lock lock = new ReentrantLock(); // Lock object
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(2); // Two threads
// Thread 1: Writes to file
executor.submit(() -> {
lock.lock(); // Locking the resource
try {
writeToFile("file1.txt", "Thread 1: Writing to file.");
} finally {
lock.unlock(); // Unlocking the resource
}
});
// Thread 2: Writes to file
executor.submit(() -> {
lock.lock(); // Locking the resource
try {
writeToFile("file2.txt", "Thread 2: Writing to file.");
} finally {
lock.unlock(); // Unlocking the resource
}
});
executor.shutdown(); // Shut down the executor
}
// Synchronized I/O method
public static void writeToFile(String fileName, String data) {
try (FileWriter writer = new FileWriter(fileName)) {
writer.write(data);
System.out.println(data + " (Written to " + fileName + ")");
} catch (IOException e) {
e.printStackTrace();
}
}
}
ব্যাখ্যা:
lock.lock()
ফাইল লেখার আগে lock গ্রহন করা হয়, এবং লেখার পর lock.unlock()
দিয়ে lock মুক্ত করা হয়।Multi-threaded I/O হল একটি প্রক্রিয়া যেখানে একাধিক থ্রেডের মাধ্যমে ইনপুট এবং আউটপুট অপারেশন সম্পাদন করা হয়, যার মাধ্যমে একাধিক I/O অপারেশন একসাথে সম্পন্ন করা যায়। এটি I/O অপারেশন আরও কার্যকর এবং দ্রুত করতে সহায়ক, কারণ এটি একাধিক থ্রেড ব্যবহার করে I/O কাজকে параллেল (parallel)ভাবে সম্পন্ন করতে পারে।
ধরা যাক, আমাদের দুটি ফাইল থেকে ডেটা পড়ে একটি নতুন ফাইলে লিখতে হবে, এবং এই কাজটি আমরা Multi-threading ব্যবহার করে কার্যকরভাবে করতে চাই।
এই উদাহরণে, দুটি ফাইল থেকে ডেটা পড়ার জন্য দুটি আলাদা থ্রেড তৈরি করা হবে, এবং তাদের আউটপুট একটি তৃতীয় ফাইলে লেখা হবে।
import java.io.*;
import java.util.concurrent.*;
public class MultiThreadedIOExample {
public static void main(String[] args) throws InterruptedException, ExecutionException {
// ExecutorService to manage threads
ExecutorService executor = Executors.newFixedThreadPool(2);
// File paths for reading data
String file1Path = "file1.txt";
String file2Path = "file2.txt";
String outputFilePath = "mergedOutput.txt";
// Submit tasks for reading data from file1 and file2
Future<String> file1Data = executor.submit(new FileReaderTask(file1Path));
Future<String> file2Data = executor.submit(new FileReaderTask(file2Path));
// Wait for both threads to finish and get the data
String dataFromFile1 = file1Data.get();
String dataFromFile2 = file2Data.get();
// Write the merged data into the output file
try (BufferedWriter writer = new BufferedWriter(new FileWriter(outputFilePath))) {
writer.write(dataFromFile1);
writer.write("\n");
writer.write(dataFromFile2);
System.out.println("Data from both files merged successfully!");
} catch (IOException e) {
e.printStackTrace();
}
// Shut down the executor
executor.shutdown();
}
// Task for reading a file and returning the data
static class FileReaderTask implements Callable<String> {
private String filePath;
public FileReaderTask(String filePath) {
this.filePath = filePath;
}
@Override
public String call() throws IOException {
StringBuilder fileContent = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
fileContent.append(line).append("\n");
}
}
return fileContent.toString();
}
}
}
ExecutorService
ব্যবহার করছি যা থ্রেড ম্যানেজমেন্টের জন্য ব্যবহার করা হয়। এটি আমাদের দুটি থ্রেড একসাথে চালাতে সাহায্য করে।Callable
টাস্ক যা ফাইল থেকে ডেটা পড়ে। Callable
ব্যবহার করা হয়েছে কারণ এটি Future
অবজেক্ট রিটার্ন করে, যা থ্রেডের কাজ শেষ হওয়ার পর ডেটা ফেরত দেয়।BufferedWriter
ব্যবহার করেছি মেমরি-ভিত্তিক আউটপুট স্ট্রীমে ডেটা লিখতে। দুটি ফাইলের ডেটা একত্রিত করে একটি নতুন ফাইলে লেখা হচ্ছে।Future.get()
:Future.get()
ব্যবহার করা হয়েছে, যা থ্রেডের কাজ শেষ হওয়া পর্যন্ত অপেক্ষা করে।executor.shutdown()
ব্যবহার করে থ্রেডের এক্সিকিউশন বন্ধ করা হয়েছে।ধরা যাক, file1.txt
এবং file2.txt
ফাইলগুলির মধ্যে কিছু টেক্সট রয়েছে। এই উদাহরণে, তাদের ডেটা mergedOutput.txt
ফাইলে একত্রিত করা হবে।
file1.txt:
Hello from file 1.
file2.txt:
Hello from file 2.
mergedOutput.txt:
Hello from file 1.
Hello from file 2.
Read more